function range(i, j) {
  return Array.from({length: j - i}, (_, k) => i + k);
}

function chord(directed, transpose) {
  function chord(matrix) {
    var n = matrix.length,
        groupIndex = range(0, n),
        chords = new Array(n * n),
        groups = new Array(n);
    matrix = Float64Array.from({length: n * n}, transpose
        ? (_, i) => matrix[i % n][i / n | 0]
        : (_, i) => matrix[i / n | 0][i % n]);
      let x = 0;
      for (const i of groupIndex) {
        const x0 = x;     
          const subgroupIndex = range(0, n).filter(j => matrix[i * n + j] || matrix[j * n + i]);
          for (const j of subgroupIndex) {
            let chord;
            if (i < j) {
              chord = chords[i * n + j] || (chords[i * n + j] );
              chord.source = {index: i, startAngle: x, endAngle: x += matrix[i * n + j], value: matrix[i * n + j]};
            } else {
              chord = chords[j * n + i] || (chords[j * n + i] );
              chord.target = {index: i, startAngle: x, endAngle: x += matrix[i * n + j], value: matrix[i * n + j]};
            }
          }        
      }
    chords.groups = groups;
  }
  return chord;
}
